package thread;

import org.junit.Test;
import util.ThreadUtil;

import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.function.*;

/**
 * @author wuguojian
 * @description
 * @date 2022/7/5 上午11:39
 **/
public class CompletableFutureTest {

    /*******************************************************************
     *  异步任务的合并执行
     * *****************************************************************
     */

    @Test
    public void test21() throws ExecutionException, InterruptedException {
        System.out.println(LocalDateTime.now());
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            ThreadUtil.sleep(2000);
            return 1;
        });
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            ThreadUtil.sleep(1000);
            return 2;
        });
        CompletableFuture<Integer> future3 = future1.thenCombine(future1, new BiFunction<Integer, Integer, Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer + integer2;
            }
        });
        System.out.println(future3.get());
        System.out.println(LocalDateTime.now());
    }





    /*******************************************************************
     *  异步任务的串行执行
     * *****************************************************************
     */


    @Test
    public void test11() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println(1);
            ThreadUtil.sleep(1000L);
            System.out.println(2);
            System.out.println("Thread Id : " + Thread.currentThread().getId());
            return 9999;
        }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
            @Override
            public CompletionStage<Integer> apply(Integer integer) {
                return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                    @Override
                    public Integer get() {
                        System.out.println("Thread Id : " + Thread.currentThread().getId());
                        return integer + 1;
                    }
                });
            }
        });
        System.out.println(future.get());
    }

    @Test
    public void test10() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println(1);
            ThreadUtil.sleep(1000L);
            System.out.println(2);
            System.out.println("Thread Id : " + Thread.currentThread().getId());
            return 9999;
        }).thenApply(new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) {
                System.out.println("Thread Id : " + Thread.currentThread().getId());
                return integer + 1;
            }
        });
        future.thenAccept(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println("thenAccept " + integer);
                System.out.println(1/0);
                System.out.println("thenAccept done");
            }
        });
        System.out.println("do sth.");
        System.out.println(future.get());
        System.out.println("finished");
    }





    /*******************************************************************
     *
     *
     * *****************************************************************
     */

    /**
     * 无输入，无返回
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test1() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            ThreadUtil.sleep(1000L);
            System.out.println(1);
        });
        System.out.println(2);
        future.get();
    }

    /**
     * 无输入，有返回
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test2() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println(1);
            ThreadUtil.sleep(1000L);
            System.out.println(2);
            return 9999;
        });
        System.out.println(8888);
        Integer integer = future.get();
        System.out.println(integer);
    }

    /**
     * 异常处理
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test3() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            ThreadUtil.sleep(1000);
            System.out.println(11);
            throw new NullPointerException("Null");
        });
        future.whenComplete(new BiConsumer<Void, Throwable>() {
            @Override
            public void accept(Void unused, Throwable throwable) {
                System.out.println("执行完成" + throwable.getMessage());
            }
        });
        future.exceptionally(new Function<Throwable, Void>() {
            @Override
            public Void apply(Throwable throwable) {
                System.out.println("执行失败:" + throwable.getMessage());
                return null;
            }
        });
        System.out.println(88888);
        future.get();
        System.out.println(99999);
    }

}
